home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Devices / Apple Desktop Bus / ADB Key Spy / Sources / Service Routine.c < prev   
Encoding:
Text File  |  1995-09-20  |  4.0 KB  |  153 lines  |  [TEXT/MMCC]

  1.     //
  2.     //    ADB Key Spy Service Routine • Pete Gontier • gurgle@apple.com
  3.     //    Macintosh Developer Technical Support
  4.     //    © 1995 Apple Computer, Inc.
  5.     //
  6.     //    See "ADB Key Spy.h" for more information.
  7.     //
  8.     //    Changes:
  9.     //
  10.     //        when        who        what
  11.     //        --------------------------------------------------------------
  12.     //        08/23/95    PG        history begins
  13.     //        08/24/95    PG        service routines split off into separate
  14.     //                            code resource for use with PowerPC
  15.     //        09/11/95    PG        first cut at virtual key map support
  16.     //        09/11/95    PG        better third-party compatibility
  17.     //
  18.  
  19. #ifndef __A4STUFF__
  20. #    include <A4Stuff.h>
  21. #endif
  22.  
  23. #include "ADB Key Spy.h"
  24.  
  25. static pascal void KeyboardServiceRoutineC (ConstStr255Param, tKeyboardInfo *);
  26. asm void __Startup__ (void);
  27.  
  28.     //
  29.     //    myDebugStr
  30.     //    DebugStrIf
  31.     //
  32.     //    These are two simple macros to aid in debugging the service routine.
  33.     //    You pretty much can't expect to use MacsBug while the service routine
  34.     //    (or any code it calls) is running. Why? Because MacsBug uses ADB to
  35.     //    talk to keyboards, and if ADB (this code) is buggy... well, you can't
  36.     //    type. If you need to debug the service routine, I suggest embedding
  37.     //    MacsBug commands in DebugStr strings followed by '; g', and
  38.     //    don't change any keys while the command is running. After
  39.     //    you call AKS_RelinquishKeyboards, you can do a post-mortem
  40.     //    analysis of the MacsBug output.
  41.     //
  42.  
  43. #define myDebugStr(x) \
  44.     do { long oldA4 = SetCurrentA4 ( ); DebugStr (x ";g"); SetA4 (oldA4); } while (0)
  45. #define myDebugStrIf(x) \
  46.     do { if (x) myDebugStr("\p" #x); } while (0)
  47.  
  48.     //
  49.     //    __Startup__
  50.     //
  51.     //    The basic idea here is to extract the information from the
  52.     //    ADB interrupt message, then call the old service routine so
  53.     //    that GetKeys still works for other folks. The interface for
  54.     //    this routine is documented in Inside Mac V-371.
  55.     //
  56.  
  57. asm void __Startup__ (void)
  58. {
  59.     //
  60.     //    is it a 'Talk' message?
  61.     //
  62.  
  63.     BTST        #2,D0
  64.     BEQ.S        bail                        // no
  65.     BTST        #3,D0
  66.     BEQ.S        bail                        // no
  67.  
  68.     //
  69.     //    is it for register 0?
  70.     //
  71.  
  72.     BTST        #0,D0
  73.     BNE.S        bail                        // no
  74.     BTST        #1,D0
  75.     BNE.S        bail                        // no
  76.  
  77.     //
  78.     //    call C function to track key change
  79.     //
  80.  
  81.     MOVEM.L        A0-A1/D0-D1,-(A7)            // save registers
  82.     MOVE.L        A0,-(A7)                    // pass ADB data buffer
  83.     MOVE.L        A2,-(A7)                    // pass private data address
  84.     JSR            KeyboardServiceRoutineC        // Geronimo!
  85.     MOVEM.L        (A7)+,A0-A1/D0-D1            // restore registers
  86.  
  87. bail:
  88.  
  89.     MOVE.L    (A2),-(A7)                        // push the previous service routine address
  90.     MOVE.L    4(A2),A2                        // set up the previous private data address
  91.     RTS                                        // jump to old service routine
  92. }
  93.  
  94.     //
  95.     //    KeyboardServiceRoutineC
  96.     //
  97.     //    This routine is called from the (68K assembly) service routine.
  98.     //    Given a pointer to a copy of the keyboard's register 0 and
  99.     //    the keyboard map for the keyboard, it updates the map.
  100.     //    Note that A5 (or A4, as the case may be) is not valid here,
  101.     //    so you will have to perform arcane rites to access global variables.
  102.     //
  103.  
  104. #pragma parameter SetD1 (__D1)
  105. void SetD1 (long) = { 0x4E71 };
  106.  
  107. static pascal void KeyboardServiceRoutineC (ConstStr255Param adbDataBuffer, tKeyboardInfo *kbInfo)
  108. {
  109.     //
  110.     //    Sanity check: have we been passed the expected number of bytes?
  111.     //
  112.  
  113.     if (adbDataBuffer [0] == 2)
  114.     {
  115.         //
  116.         //    Find the the virtual key map entry affected by the
  117.         //    given raw key code. If there is no translator resource,
  118.         //    don't translate.
  119.         //
  120.     
  121.         unsigned char        *keyMapEntry        = kbInfo->virtualKeyMap;
  122.         tKeyMapResourceH    keyMapResH            = kbInfo->keyMapResH;
  123.         unsigned char        adbDataBufferIndex    = 1;
  124.  
  125.         do
  126.         {
  127.             unsigned char adbByte = adbDataBuffer [adbDataBufferIndex];
  128.  
  129.             if (adbByte != 0xFF)
  130.             {
  131.                 unsigned char rawKeyCodeIndex = 0x7F & adbByte;
  132.             
  133.                 if (!keyMapResH)
  134.                     keyMapEntry += rawKeyCodeIndex;
  135.                 else
  136.                     keyMapEntry += (**keyMapResH).map [rawKeyCodeIndex];
  137.             
  138.                 //
  139.                 //    If a key is going down, increment its counter.
  140.                 //    If instead it's going up, make sure its counter
  141.                 //    can be decremented before decrementing it.
  142.                 //
  143.             
  144.                 if (!(0x80 & adbByte))
  145.                     *keyMapEntry += 1;
  146.                 else if (*keyMapEntry)
  147.                     *keyMapEntry -= 1;
  148.             }
  149.         }
  150.         while (++adbDataBufferIndex <= 2);
  151.     }
  152. }
  153.